import os
import numpy as np
import pandas as pd
from PIL import Image
from keras.utils import np_utils
from keras.models import Sequential, Model  # keras的神经网络模型
from keras.layers import Dense  # 全连接层



class DeepLearn(object):
    """深度学习类"""

    def __init__(self, pred_path):
        """1. 准备数据，构建数据"""
        path = os.path.abspath(os.path.dirname(__file__)) + os.sep
        file_path = path + "data" + os.sep + "mnist.npz"
        # print(file_path)
        f = np.load(file_path)
        x_train = f['x_train']  # 训练特征集
        x_test = f['x_test']  # 测试特征集
        y_train = f['y_train']  # 训练目标集
        y_test = f['y_test']  # 测试目标集
        # print(x_train.shape)
        # print(x_test.shape)
        # print(y_train.shape)
        # print(y_test.shape)
        # from keras.utils import np_utils
        # todo 规定一些数据的大小
        self.img_size = 28 * 28  # 图像尺寸
        self.num_size = 10  # 目标数字的尺寸
        self.batch_size = 128  # 批量的尺寸
        self.nb_epochs = 2  # 迭代次数

        # todo 特征数据的处理，优化
        # 降维度， 把3维数据降为2维 (60000, 28, 28)-->(60000,28*28)
        # 灰度数据， 从unit8  --》 double方式
        self.x_train = (x_train.reshape(60000, self.img_size).astype("float32")) / 255
        self.x_test = (x_test.reshape(10000, self.img_size).astype("float32")) / 255

        # todo 目标集数据的处理： 采用独热编码：one-hot 编码 ， 将unit8 编码 转为 独热编码
        self.y_train = np_utils.to_categorical(y_train, self.num_size)
        self.y_test = np_utils.to_categorical(y_test, self.num_size)

        # todo 预测图片的处理
        # PIL有九种不同的模式 1，L ,P,RGB,CMYK...
        img = Image.open(pred_path).resize((28, 28)).convert("L")  # 灰度化
        im_arr = np.array(img)
        # 降低维度
        pred_img = (im_arr.reshape(1, self.img_size).astype("float32")) / 255
        self.pred_img = pred_img

    def dnn_keras(self):
        """浅层神经网络模型"""
        # 2. 构造模型  #Dense : 10: 输出的类型  ， input_shape 输入  ， activation：激活函数
        model = Sequential([Dense(10, input_shape=(self.img_size,), activation="softmax")])

        # 3.编译模型 ： 用于指定优化器， 损失函数 ， 测量方式等
        # optimizer="rmsprop"-->指定优化器为 动量梯度下降法
        model.compile(optimizer="rmsprop", loss="categorical_crossentropy", metrics=["accuracy"])

        # 4. 模型训练  verbose:日志提示方式
        model.fit(self.x_train, self.y_train, batch_size=self.batch_size,
                  epochs=10, verbose=1, validation_data=(self.x_test, self.y_test))
        # 5. 模型评估
        metr = model.evaluate(self.x_test, self.y_test, verbose=0)  # 返回误差和得分
        # print(metr)
        score = round(metr[1], 2)
        score = "DNN模型正确率:" + str(score)
        print(score)

        # 6 模型应用
        pred = model.predict(self.pred_img)
        # 结果解码
        pred = np.argmax(pred)
        pred = "预测的结果是:" + str(pred)
        # print(pred)
        return pred,score

if __name__ == '__main__':
    dl = DeepLearn("0.png")
    dl.dnn_keras()
